package objekte;

/**Ein Speicher kann beliebig viele Objekte aufnehmen, wieder finden und
 * wieder entfernen. Die Einfügung von null ist nicht möglich.
 */
public class Speicher{
  private Object[] zeug;

  /**Erzeugt einen Speicher mit gegebener Anfangskapazität.
   * @param anz die gewünschte Anfangskapazität
   */
  public Speicher(int anz){
    zeug=new Object[anz];
  }

  /**Erzeugt einen Speicher mit einer Anfangskapazität von
   * 4 Einträgen.
   */
  public Speicher(){
    this(4);
  }

  /**Gibt die Anzahl der schon belegten Plätze zurück.
   * @return die Anzahl der belegten Plätze.
   */
  public int size(){
    for(int i=0; i<zeug.length; i++)
      if(zeug[i]==null) return i;
    return zeug.length;
  }

  /**Sucht im Speicher nach einem bestimmten Eintrag.
   * @param was das im Speicher zu suchende Object.
   * @return die Position im Speicher oder -1, falls es nicht drin ist.
   */
  public int indexOf(Object was){
    for(int i=0; i<zeug.length; i++)
      if(zeug[i]==was) return i;
    return -1;
  }

  /**Fügt ein Object an der gewünschten Position ein. Es werden aber keine
   * Plätze leer gelassen. null wird nicht eingefügt.
   * @param was das in den Speicher einzufügende Object.
   * @param pos die Position, an der eingefügt werden soll. Ist sie größer
   *   als die Position des ersten freien Platzes, wird an diesem ersten freien
   *   Platz eingefügt. Ist pos&lt;0, wird ganz vorne eingefügt. Ist die
   *   angegebene Position schon belegt, rücken alle Einträge ab dieser Position
   *   nach rechts.
   * @return die Position, an der das Element eingefügt wurde, oder -1, falls
   *   versucht wurde, null einzufügen.
   */
  public int insert(Object was, int pos){
    if(was==null) return -1;
    if(pos<0) pos=0;
    int s=size();
    if(pos>s) pos=s;
    Object[] merk=zeug;
    if(s==zeug.length){
      zeug=new Object[s*2];
      for(int i=0; i<pos; i++)
        zeug[i]=merk[i];
    }
    for(int i=s; i>pos; i--)
      zeug[i]=merk[i-1];
    zeug[pos]=was;
    return pos;
  }

  /**Fügt das angegebene Object hinten an.
   * @param wer das anzufügende Object.
   * @return die Position, an der das Element eingefügt wurde, oder -1, falls
   *   versucht wurde, null einzufügen.
   */
  public int insert(Object wer){
    return insert(wer, size());
  }

  /**Gibt das Object an der gegebenen Position zurück.
   * @param pos die gewünschte Position.
   * @return das dort gefundene Object oder null, wenn die Position
   *   nicht besetzt ist.
   */
  public Object get(int pos){
    if(pos<0 || pos>=size()) return null;
    return zeug[pos];
  }

  /**Entfernt das Object an der gegebenen Position und liefert es zurück.
   * @param pos die Position des zu löschenden Objects.
   * @return das gelöschte Object.
   */
  public Object delete(int pos){
    Object ret=get(pos);
    int s=size()-1;
    while(pos<s)
      zeug[pos]=zeug[++pos];
    zeug[pos]=null;
    return ret;
  }

  public String toString(){
    return "Liste von Objects mit "+size()+" Einträgen.";
  }

  // Der Rest ist nur fürs Testen da.
  public static void main(String[] args){
    Speicher speicher=new Speicher();
    speicher.insert("Leute");
    ausgabe(speicher);
    speicher.insert("Hallo", 0);
    ausgabe(speicher);
    System.out.println("besetzt="+speicher.size());
  }

  public static void ausgabe(Speicher s){
    for(int i=0, n=s.size(); i<n; i++)
      System.out.print("("+i+":"+s.get(i)+") ");
    System.out.println();
  }
}
